<?php
/**
 *  购物车推荐商品
 */

namespace Biz\service;

use Biz\service\Recommend as sRecommend;
use Biz\cache\CartRecommend as cCartRecommend;
use Biz\service\search\Goods as ssGoods;
use Biz\service\Goods as sGoods;
use Biz\model\GoodsBasicInfo as mGoodsBasicInfo;
use Biz\model\trade\Cart as mCart;
use Biz\model\trade\CartV as mCartV;
use Biz\model\trade\OrderGoods as mOrderGoods;
use Biz\tools\IsTestShop as tIsTestShop;
use Doraemon\service\ABTest\ABFactory as sABFactory;
use Doraemon\model\MemberExtendInfo as mMemberExtendInfo;
use Doraemon\tools\Log as tLog;
use Biz\service\esSearch\Goods as esGoods;
/**
 * @deprecated
 */
class CartRecommend
{
    const CATEGORY_CODE_CONFIG_FILE = "/home/adm_rsync_dir/category_code.json";
    public static $cartData;
    public static $recommendData = [];
    public static $pageSize = 40;

    const AB_TEST_A = 'a';
    const AB_TEST_B = 'b';

    /**
     * @desc 错误日志
     * @param string $title 日志名称
     * @param array $params 存储参数
     * @return mixed
     */
    public static function errorLog($title, array $params)
    {
        tLog::warning('购物车推荐::' . $title, $params);
    }

    /**
     * @desc 购物车推荐商品流程
     * @param int $uid 用户id
     * @param int $vid 游客id
     * @param int $page 页码
     * @param int $maxCount 推荐商品最大数量
     * @return mixed
     */
    public static function main($uid, $vid, $page, $maxCount = 40)
    {
        $response = [];
        try {

            //页码校验
            if ($page < 1 || $page  > ceil($maxCount / self::$pageSize)) throw new \Exception('页码超出限制');

            //AB测试用户标识
            $sign = self::getABSign($uid);

            //用户的装修状态
            $decorationStatus = mMemberExtendInfo::getDecorationStatus($uid);

            //用户购物车商品id集合
            if ($uid > 0) {
                self::getUserCartGoodsIds($uid);
            } else {
                if (strlen($vid) > 0) {
                    self::getVUserCartGoodsIds($vid);
                }
            }

            if (!isset(self::$cartData)) {
                self::$cartData = [];
            }

//            if ($sign == self::AB_TEST_A || $uid == 0)
            if (false)
            {
                //A类用户，基础推荐给出的商品过滤后，留下40个商品，分2次加载；所有商品的排序不做特殊要求
                $response = self::baseRules($decorationStatus, $maxCount);
            }
            else
            {
                //B类用户，算法给出一个推荐商品list，过滤后如果不足40个，再由基础推荐补足

                //todo 推荐商品（算法推荐）
                $recommendRules = sRecommend::cartRecommendation($uid, self::$pageSize);

                //过滤推荐算法
                $goodsIds = self::filterRules($recommendRules);
                self::$recommendData = $goodsIds;

                //基础推荐补充
                $baseCount = $maxCount - count($goodsIds);
                if ($baseCount > 0) {
                    $base = self::baseRules($decorationStatus, $baseCount);
                } else {
                    $base = [];
                }
                $response = array_merge($goodsIds, $base);
            }
        } catch (\Exception $e) {
            //todo 记录错误日志
            self::errorLog('购物车推荐商品流程', [
                'line'  => $e->getLine(),
                'message' => $e->getMessage(),
                'rs' => $response,
                'args' => func_get_args()
            ]);
        } finally {
            //分页处理
            $offset = ($page - 1) * self::$pageSize;
            $response = array_slice($response, $offset, self::$pageSize);
            return array_values(sGoods::Goods($response));
        }
    }

    /**
     * @desc 指定类目下热卖商品的topN
     * @param int $categoryId 类目id
     * @return array
     */
    public static function getHotGoodsByCategory($categoryId)
    {
        if (cCartRecommend::categoryExists($categoryId)) {
            return cCartRecommend::getRecommendIds($categoryId);
        }
        //取最近3个月
        $startTime= date("Y-m-d H:i:s", strtotime("-3 month"));
        $endTime  = date("Y-m-d H:i:s");

        //获取类目下的商品id集合
        $goodsIds = mGoodsBasicInfo::getGoodsIdsByCategoryId($categoryId);
        $goodsIds = $goodsIds ? array_column($goodsIds, 'goods_id') : [];

        //获取线上测试店铺
        $testShopIds = tIsTestShop::getTestShopIds();

        // 热门所需数据 30 : 10 : 10

        //加入购物车最多的商品
        $cartHotGoodsIds = mCart::getHotRankGoodsId($startTime, $endTime, $testShopIds);
        $cartHotGoodsIds = array_intersect($goodsIds, $cartHotGoodsIds);
        $cartList = mCart::getHotRank($startTime, $endTime, $limit = 30, $testShopIds, $cartHotGoodsIds);
        $cartList = $cartList ? array_column($cartList, 'goods_id') : [];

        //支付金额最多的商品排名数据
        $payRankGoodsIds = mOrderGoods::getPayRankGoodsIds($startTime, $endTime, $testShopIds);
        $payRankGoodsIds = array_intersect($goodsIds, $payRankGoodsIds);
        $orderGoodsSumList = mOrderGoods::getPayAmountRank($startTime, $endTime, $limit = 10, $testShopIds, $payRankGoodsIds);
        $orderGoodsSumList = $orderGoodsSumList ? array_column($orderGoodsSumList, 'goods_id') : [];

        //下单最多的商品排名数据
        $orderGoodsCountList = mOrderGoods::getBuyAmountRank($startTime, $endTime, $limit = 10, $testShopIds, $payRankGoodsIds);
        $orderGoodsCountList = $orderGoodsCountList ? array_column($orderGoodsCountList, 'goods_id') : [];
        $hotGoods  = array_unique(array_merge($cartList, $orderGoodsSumList, $orderGoodsCountList));

        //打乱数据
        shuffle($hotGoods);

        //设置缓存
        cCartRecommend::setRecommendIds($categoryId, $hotGoods);

        return $hotGoods;
    }

    /**
     * @desc 基础推荐规则
     * @param int $decorationStatus 装修状态
     * @param int $maxCount 推荐商品数量
     * @return array
     */
    public static function baseRules($decorationStatus, $maxCount)
    {
        //根据装修状态获取类目
        switch ($decorationStatus) {
            case mMemberExtendInfo::STATUS_DECORATION_PLAN:
            case mMemberExtendInfo::STATUS_DECORATION_ON:
            case mMemberExtendInfo::STATUS_DECORATION_INROOM:
            case mMemberExtendInfo::STATUS_DECORATION_NOPLAN:
                $category = self::decorationStatusConfig($decorationStatus);
                break;
            default://没有装修状态的情况
                $category = [];
                break;
        }

        //遍历获取类目下的热卖商品
        $hotCount = 0;
        $goodsIds = [];
        foreach ($category as $categoryName => $v) {
            $categoryId = self::categoryTopMap($categoryName);
            $need = ceil($maxCount * $v / 100);
            $hotGoodsIds = self::getHotGoodsByCategory($categoryId);

            //过滤
            $hotGoodsIds = self::filterRules($hotGoodsIds);
            $hotGoodsIds = array_slice($hotGoodsIds, 0, $need);

            $goodsIds = array_merge($hotGoodsIds, $goodsIds);
            $hotCount += count($hotGoodsIds);
        }

        //需要补充的量
        $surplus = $maxCount - $hotCount;
        //热卖的商品不足N，剩下的商品全部用家居装饰补足
        if ($surplus > 0) {
            $lastGoods = self::getLastGoods($goodsIds, $page = 1, $surplus);
            $goodsIds = array_merge($goodsIds, $lastGoods);
        }
        return $goodsIds;
    }

    /**
     * @desc 过滤规则
     * @note
        符合以下任意一个条件的商品，都在推荐商品中屏蔽
            状态=下架或已删除
            总库存=0
            商品标签=屏蔽商品
            商品所属店铺，在限流店铺名单
            店铺uid=3192940或3657469，属于线上的测试店铺
            商品SPU已经在当前用户的购物车里
     * @param array $goodsIds
     * @return array
     */
    public static function filterRules(array $goodsIds)
    {
        //排除用户购物车中的商品
        $goodsIds = array_diff($goodsIds, self::$cartData);

        //排除用户购物车中的商品
        $goodsIds = array_diff($goodsIds, self::$recommendData);

        //过滤屏蔽商品
        $where = [
            'app_status' => mGoodsBasicInfo::STATUS_APP_NOMAL,
            'id' => $goodsIds,
            'source' => esGoods::SOURCE_APP
        ];
        $response = SearchGoods::searchEntrance($where, esGoods::SCENES_CART_RECOMMEND, 0, 1, count($goodsIds));
        // todo 搜索切换es待删除
//        $response = ssGoods::filterShieldGoodsIds($goodsIds, $addCondition);
        return $response['rows'] ? $response['rows']: [] ;
    }

    /**
     * @desc 获取AB用户分组标识
     * @param int $uid 用户id
     * @param int $abType 分组类型
     * @param array $abConfig 比例配置
     * @return string
     */
    public static function getABSign ($uid, $abType = sABFactory::AB_UID, array $abConfig = [50, 50])
    {
        return $uid % 2 == 0 ? self::AB_TEST_A : self::AB_TEST_B;
//        $abFactory = new sABFactory();
//        $abClass = $abFactory->create($abType);
//        foreach($abConfig as $val){
//            $abClass->setABMaps($val);
//        }
//        $abClass->setUid($uid);
//        return $abClass->getABTest();
    }

    /**
     * @desc 获取已经在当前用户的购物车里的商品id集合
     * @param int $uid 用户id
     * @return array
     */
    private static function getUserCartGoodsIds ($uid)
    {
        if (!isset(self::$cartData)) {
            $cartGoods = mCart::getGoodsIdsByUid($uid);
            self::$cartData = $cartGoods ? array_column($cartGoods, 'goods_id') : [];
        }
        return self::$cartData;
    }

    /**
     * @desc 获取已经在当前游客的购物车里的商品id集合
     * @param int $uid 用户id
     * @return array
     */
    private static function getVUserCartGoodsIds ($uid)
    {
        if (!isset(self::$cartData)) {
            $cartGoods = mCartV::getGoodsIdsByUid($uid);
            self::$cartData = $cartGoods ? array_column($cartGoods, 'goods_id') : [];
        }
        return self::$cartData;
    }

    /**
     * @desc 补充推荐商品
     * @note 剩下的商品全部用家居装饰补足
     * @param array $hotGoods 热卖商品id集合
     * @param int $page 页码
     * @param int $pageSize 分页数量
     * @return array
     */
    private static function getLastGoods ($hotGoods, $page, $pageSize)
    {
        $categoryIds = [
            2
        ];

        $goodsIds = array_merge(self::$cartData, self::$recommendData, $hotGoods);

        $where = [
            'app_status' => mGoodsBasicInfo::STATUS_APP_NOMAL,
            'category_id' => $categoryIds,
            'id[!]' => array_values($goodsIds),
            'source' => esGoods::SOURCE_APP,
        ];
        $rs = SearchGoods::searchEntrance($where, esGoods::SCENES_CART_RECOMMEND, 0, $page, $pageSize);
        // todo 搜索切换es待删除
//        $rs = ssGoods::searchGoodsByTopCateIds($categoryIds, $goodsIds, $addCondition, $page, $pageSize);

        return $rs['rows'] ? : $rs['rows'];
    }

    /**
     * @desc 一级类目名称与id映射
     * @param string $categoryName 类目名称
     * @return int
     */
    public static function categoryTopMap($categoryName)
    {
        $map = [
            '家具' => 1,
            '家居装饰' => 2,
            '家居日用' => 3,
            '家电' => 4,
            '灯饰建材' => 5,
            '智能家居' => 115,
            '宠物用品' => 120,
            '虚拟商品' => 401,
        ];
        return $map[$categoryName] ?? 0;
    }
    /**
     * @desc 装修状态与类目的对应关系及比例
     * @note
    准备装修
    灯饰建材（30%）、家具（30%）、家居装饰（20%）、家居日用（10%）、家电（5%）、宠物用品（5%）
    正在装修
    家具（50%）、灯饰建材（20%）、家居装饰（10%）、家居日用（10%）、家电（5%）、宠物用品（5%）
    已经入住/暂无计划
    家居装饰（40%）、家居日用（30%）、宠物用品（10%）、家电（20%）
     * @param int $decorationStatus 装修状态
     * @return array
     */
    public static function decorationStatusConfig($decorationStatus)
    {
        $map = [
            //准备装修
            mMemberExtendInfo::STATUS_DECORATION_PLAN => [
                '灯饰建材' => 30,
                '家具' => 30,
                '家居装饰' => 20,
                '家居日用' => 10,
                '家电' => 5,
                '宠物用品' => 5,
            ],
            //正在装修
            mMemberExtendInfo::STATUS_DECORATION_ON => [
                '家具' => 50,
                '灯饰建材' => 20,
                '家居装饰' => 10,
                '家居日用' => 10,
                '家电' => 5,
                '宠物用品' => 5,
            ],
            //已经入住
            mMemberExtendInfo::STATUS_DECORATION_INROOM => [
                '家居装饰' => 40,
                '家居日用' => 30,
                '家电' => 20,
                '宠物用品' => 10,
            ],
            //暂无计划
            mMemberExtendInfo::STATUS_DECORATION_NOPLAN => [
                '家居装饰' => 40,
                '家居日用' => 30,
                '家电' => 20,
                '宠物用品' => 10,
            ],
        ];
        return $map[$decorationStatus] ?? [];
    }

}